/*
 * =====================================================================================
 *       Filename:  circle.h
 *         Author:  MIEN
 *    Description:  生产者/消费者模式的环形队列
 *           Date:  2016-11-16
 * =====================================================================================
 */

#include <pthread.h>

#ifndef CIRCLE_H
#define CIRCLE_H

/* 队列节点 */
typedef struct circleNode {
    struct circleNode *next;
    void *value;
} circleNode;

/* 线程结构预声明 */
struct circleThread;

/* 队列 */
typedef struct circleQueue {
    circleNode *empty;                          /* 指向可装载任务的节点 */
    circleNode *fresh;                          /* 与empty相差一个节点的跟随节点(刚装载或正装载任务) */
    circleNode *full;                           /* 指向有处理任务的节点 */

    void (*free) (void* ptr);                   /* 释放环形队列时，销毁各节点的value的方法 */
    void (*produce) (void *data, void **value); /* 生产者方法 */
    void (*consume) (void *value);              /* 消费者方法 */

    unsigned long capacity;                     /* 队列节点数目 */
    unsigned long tasks;                        /* 待做的任务数目 */

    pthread_mutex_t lock;                       /* 用于同步的互斥锁 */
    pthread_cond_t sig;                         /* 用于阻塞的条件变量 */

    struct circleThread *ct;                    /* 消费者线程 */
    int loop;                                   /* 队列状态, 初始为1 (1,运行; 0,停止) */
} circleQueue;

/* 线程 */
typedef struct circleThread {
    struct circleThread *next;
    pthread_t id;                   /* 线程id */
    void* (*proc) (void *value);    /* 线程方法 */
    void *value;                    /* 用于装载当前数据，与circleNode中的value类型一致 */
    circleQueue* circle;            /* 所属的队列 */
} circleThread;

/* 宏定义实现的方法 */
#define circleCapacity(l) ((l)->capacity)
#define circleTasks(l) ((l)->tasks)

#define circleSetFreeMethod(l,m) ((l)->free = (m))
#define circleSetProduceMethod(l,m) ((l)->produce = (m))
#define circleSetConsumeMethod(l,m) ((l)->consume = (m))

/* 创建和释放 */
circleQueue* circleCreate(void);
void circleRelease(circleQueue *circle);

/* 推入待加工数据 */
void circlePushIn(circleQueue *circle, void* data);

/* 增加消费者线程 */
void circleAddConsumer(circleQueue *circle);

/* 开启循环 */
void circleLoop(circleQueue *circle);

/* 退出循环 */
void circleQuit(circleQueue *circle);

#endif /* CIRCLE_H */
